﻿using Microsoft.AspNetCore.SignalR;

namespace SignalRServerDemo.Hubs
{
    public class CustomHub : Hub<ClientData>
    {
        private readonly ILogger<CustomHub> _logger;

        public CustomHub(ILogger<CustomHub> logger)
        {
            _logger = logger;
        }

        public override Task OnConnectedAsync()
        {
            string deviceId = string.Empty;
            var httpContext = Context.GetHttpContext();
            if (httpContext != null)
            {
                deviceId = httpContext.Request.Query["deviceId"];
                //_logger.LogInformation($"设备编号：{deviceId}");
            }

            _logger.LogInformation($"建立连接，设备编号：{deviceId}，连接编号：{Context.ConnectionId} - {DateTime.Now}");
            return base.OnConnectedAsync();
        }

        public override Task OnDisconnectedAsync(Exception? exception)
        {
            string deviceId = string.Empty;
            var httpContext = Context.GetHttpContext();
            if (httpContext != null)
            {
                deviceId = httpContext.Request.Query["deviceId"];
                //_logger.LogInformation($"设备编号：{deviceId}");
            }

            if (exception != null)
            {
                _logger.LogError(exception, $"断开连接，设备编号：{deviceId}，连接编号：{Context?.ConnectionId} - {DateTime.Now}");
            }
            else
            {
                _logger.LogInformation($"断开连接，设备编号：{deviceId}，连接编号：{Context?.ConnectionId} - {DateTime.Now}");
            }

            return base.OnDisconnectedAsync(exception);
        }

        /// <summary>
        /// 建立通信
        /// </summary>
        public void BeginSendData(TransData data)
        {
            _logger.LogInformation("建立通信，接收数据：{0},{1}", data.id, data.message);
        }

        /// <summary>
        /// 单一客户端调用 通信
        /// 仅仅通知 调用的那个客户端 其余建立链接的客户端不生成通信
        /// </summary>
        public Task SingleClientCaller(TransData data)
        {
            _logger.LogInformation("仅通知当前客户端，接收数据：{0},{1}", data.id, data.message);

            return Clients.Caller.ClientHook(new TransData(data.id, data.message));
        }

        /// <summary>
        /// 所有客户端建立通信
        /// 可通知所有的客户端
        /// </summary>
        public Task AllClientResponse(TransData data)
        {
            _logger.LogInformation("通知所有的客户端，接收数据：{0},{1}", data.id, data.message);

            return Clients.All.ClientHook(new TransData(data.id, data.message));
        }

        /// <summary>
        /// 指定方法名调用
        /// </summary>
        [HubMethodName("get_date")]
        public TransData InvokeData()
        {
            return new TransData(Guid.NewGuid().ToString(), $"当前时间：{DateTime.Now}");
        }

        /// <summary>
        /// 加入组
        /// </summary>
        public Task JoinGroup(GroupData data)
        {
            _logger.LogInformation("加入组，接收数据：{0},{1}", data.id, data.groupId);
            return Groups.AddToGroupAsync(Context.ConnectionId, data.groupId);
        }

        /// <summary>
        /// 离开组
        /// </summary>
        public Task LeaveGroup(GroupData data)
        {
            _logger.LogInformation("离开组，接收数据：{0},{1}", data.id, data.groupId);
            return Groups.RemoveFromGroupAsync(Context.ConnectionId, data.groupId);
        }

        /// <summary>
        /// 发送组消息
        /// </summary>
        public Task SendGroupMessage(GroupMessage message)
        {
            _logger.LogInformation("发送组消息，接收数据：{0},{1},{2}", message.id, message.groupId, message.message);
            return Clients.Groups(message.groupId).ClientHook(new TransData(message.id, message.message));
        }

        /// <summary>
        /// 发送组消息（排除自己）
        /// </summary>
        public Task SendGroupMessageExcludeSelf(GroupMessage message)
        {
            _logger.LogInformation("发送组消息（排除自己），接收数据：{0},{1},{2}", message.id, message.groupId, message.message);
            return Clients.GroupExcept(message.groupId, Context.ConnectionId).ClientHook(new TransData(message.id, message.message));
        }

        /// <summary>
        /// 心跳
        /// </summary>
        public void Heartbeat(HeartbeatData data)
        {
            string deviceId = string.Empty;
            var httpContext = Context.GetHttpContext();
            if (httpContext != null)
            {
                deviceId = httpContext.Request.Query["deviceId"];
                //_logger.LogInformation($"设备编号：{deviceId}");
            }

            _logger.LogInformation($"心跳，设备编号：{deviceId}，连接编号：{Context?.ConnectionId} - {DateTime.Now}，消息：{data.message}");
        }

        /// <summary>
        /// 挂断
        /// </summary>
        public void Goodbye()
        {
            string deviceId = string.Empty;
            var httpContext = Context.GetHttpContext();
            if (httpContext != null)
            {
                deviceId = httpContext.Request.Query["deviceId"];
                //_logger.LogInformation($"设备编号：{deviceId}");
            }

            _logger.LogInformation($"挂断连接，设备编号：{deviceId}，连接编号：{Context.ConnectionId} - {DateTime.Now}");

            Context.Abort();
        }
    }

    public interface ClientData
    {
        Task ClientHook(TransData data);
    }

    public record TransData(string id, string message);
    public record GroupData(string id, string groupId);
    public record GroupMessage(string id, string groupId, string message);
    public record HeartbeatData(string message);
}
